package com.hotel.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hotel.entity.Room;
import com.hotel.entity.RoomType;
import com.hotel.dto.RoomDTO;
import com.hotel.vo.RoomVO;
import com.hotel.mapper.RoomMapper;
import com.hotel.mapper.RoomTypeMapper;
import com.hotel.service.RoomService;
import com.hotel.service.RoomTypeService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 房间服务实现类
 */
@Service
public class RoomServiceImpl extends ServiceImpl<RoomMapper, Room> implements RoomService {
    
    @Autowired
    private RoomMapper roomMapper;
    
    @Autowired
    private RoomTypeMapper roomTypeMapper;
    
    @Autowired
    private RoomTypeService roomTypeService;
    
    @Override
    public Page<RoomVO> getRoomPage(int current, int size, String keyword, String status, Integer floor) {
        Page<Room> page = new Page<>(current, size);
        
        LambdaQueryWrapper<Room> wrapper = new LambdaQueryWrapper<>();
        
        // 关键词搜索
        if (StringUtils.hasText(keyword)) {
            wrapper.like(Room::getRoomNumber, keyword);
        }
        
        // 状态过滤
        if (StringUtils.hasText(status)) {
            wrapper.eq(Room::getStatus, status);
        }
        
        // 楼层过滤
        if (floor != null) {
            wrapper.eq(Room::getFloor, floor);
        }
        
        wrapper.orderByAsc(Room::getFloor).orderByAsc(Room::getRoomNumber);
        
        Page<Room> roomPage = this.page(page, wrapper);
        
        // 转换为VO
        Page<RoomVO> voPage = new Page<>();
        BeanUtils.copyProperties(roomPage, voPage);
        
        List<RoomVO> voList = roomPage.getRecords().stream().map(room -> {
            RoomVO vo = new RoomVO();
            BeanUtils.copyProperties(room, vo);
            
            // 获取房型信息
            if (room.getRoomTypeId() != null) {
                RoomType roomType = roomTypeMapper.selectById(room.getRoomTypeId());
                if (roomType != null) {
                    vo.setRoomTypeName(roomType.getTypeName());
                    vo.setPrice(roomType.getPrice());
                    vo.setBedType(roomType.getBedType());
                    vo.setMaxOccupancy(roomType.getMaxGuests());
                }
            }
            
            return vo;
        }).collect(Collectors.toList());
        
        voPage.setRecords(voList);
        return voPage;
    }
    
    @Override
    public RoomVO getRoomById(Long id) {
        Room room = this.getById(id);
        if (room == null) {
            return null;
        }
        
        RoomVO vo = new RoomVO();
        BeanUtils.copyProperties(room, vo);
        
        // 获取房型信息
        if (room.getRoomTypeId() != null) {
            RoomType roomType = roomTypeMapper.selectById(room.getRoomTypeId());
            if (roomType != null) {
                vo.setRoomTypeName(roomType.getTypeName());
                vo.setPrice(roomType.getPrice());
                vo.setBedType(roomType.getBedType());
                vo.setMaxOccupancy(roomType.getMaxGuests());
            }
        }
        
        return vo;
    }
    
    @Override
    @Transactional
    public boolean createRoom(RoomDTO roomDTO) {
        // 检查房间号是否已存在
        Room existingRoom = this.getRoomByNumber(roomDTO.getRoomNumber());
        if (existingRoom != null) {
            return false;
        }
        
        Room room = new Room();
        BeanUtils.copyProperties(roomDTO, room);
        
        // 设置默认状态为可用
        if (!StringUtils.hasText(room.getStatus())) {
            room.setStatus("available");
        }
        
        room.setCreateTime(LocalDateTime.now());
        
        return this.save(room);
    }
    
    @Override
    @Transactional
    public boolean updateRoom(Long id, RoomDTO roomDTO) {
        Room room = this.getById(id);
        if (room == null) {
            return false;
        }
        
        // 检查房间号是否已被其他房间使用
        if (!room.getRoomNumber().equals(roomDTO.getRoomNumber())) {
            Room existingRoom = this.getRoomByNumber(roomDTO.getRoomNumber());
            if (existingRoom != null) {
                return false;
            }
        }
        
        BeanUtils.copyProperties(roomDTO, room);
        
        return this.updateById(room);
    }
    
    @Override
    @Transactional
    public boolean deleteRoom(Long id) {
        return this.removeById(id);
    }
    
    @Override
    public Room getRoomByNumber(String roomNumber) {
        LambdaQueryWrapper<Room> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Room::getRoomNumber, roomNumber);
        return this.getOne(wrapper);
    }
    
    @Override
    @Transactional
    public boolean updateRoomStatus(Long roomId, String status) {
        Room room = this.getById(roomId);
        if (room == null) {
            return false;
        }
        
        room.setStatus(status);
        
        return this.updateById(room);
    }
    
    @Override
    @Transactional
    public boolean batchUpdateRoomStatus(List<Long> roomIds, String status) {
        if (roomIds == null || roomIds.isEmpty()) {
            return false;
        }
        
        List<Room> rooms = this.listByIds(roomIds);
        for (Room room : rooms) {
            room.setStatus(status);
        }
        
        return this.updateBatchById(rooms);
    }
    
    @Override
    public List<RoomVO> getAvailableRooms(Long roomTypeId, String checkinDate, String checkoutDate) {
        List<Room> availableRooms = roomMapper.getAvailableRooms(roomTypeId, checkinDate, checkoutDate);
        
        return availableRooms.stream().map(room -> {
            RoomVO vo = new RoomVO();
            BeanUtils.copyProperties(room, vo);
            
            // 获取房型信息
            if (room.getRoomTypeId() != null) {
                RoomType roomType = roomTypeMapper.selectById(room.getRoomTypeId());
                if (roomType != null) {
                    vo.setRoomTypeName(roomType.getTypeName());
                    vo.setPrice(roomType.getPrice());
                    vo.setBedType(roomType.getBedType());
                    vo.setMaxOccupancy(roomType.getMaxGuests());
                }
            }
            
            return vo;
        }).collect(Collectors.toList());
    }
    
    @Override
    public Map<String, Object> getRoomStatusStats() {
        List<Map<String, Object>> statusStats = roomMapper.getRoomStatusStats();
        
        Map<String, Object> result = new HashMap<>();
        int total = 0;
        
        for (Map<String, Object> stat : statusStats) {
            String status = (String) stat.get("status");
            Long count = (Long) stat.get("count");
            result.put(status, count);
            total += count;
        }
        
        result.put("total", total);
        return result;
    }
    
    @Override
    public List<Map<String, Object>> getFloorRoomDistribution() {
        return roomMapper.getFloorRoomDistribution();
    }
    
    @Override
    @Transactional
    public boolean markRoomCleaned(Long roomId) {
        Room room = this.getById(roomId);
        if (room == null) {
            return false;
        }
        
        int rows = roomMapper.updateRoomCleanTime(roomId);
        return rows > 0;
    }
    
    @Override
    @Transactional
    public boolean markRoomMaintained(Long roomId) {
        Room room = this.getById(roomId);
        if (room == null) {
            return false;
        }
        
        int rows = roomMapper.updateRoomMaintenanceTime(roomId);
        return rows > 0;
    }
    
    @Override
    public List<Map<String, Object>> getRoomCheckinHistory(Long roomId, int limit) {
        return roomMapper.getRoomCheckinHistory(roomId, limit);
    }
    
    @Override
    public boolean isRoomAvailable(Long roomId, String checkinDate, String checkoutDate) {
        Room room = this.getById(roomId);
        if (room == null || !"available".equals(room.getStatus())) {
            return false;
        }
        
        int count = roomMapper.checkRoomAvailability(roomId, checkinDate, checkoutDate);
        return count == 0;
    }
}